package com.demo.java.OD451_500.OD455;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

/**
 * @author bug菌
 * @Source 公众号：猿圈奇妙屋
 * @des： 【伐木工(C&D卷)】问题
 * @url： https://blog.csdn.net/weixin_43970743/article/details/146341119
 */
public class OdMain {
    // 判断是否需要更新 list
    private static boolean shouldUpdateList(List<Integer> oldList, List<Integer> list1, List<Integer> list2) {
        return oldList.size() > list1.size() + list2.size();
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int X = scanner.nextInt();  // 读取木材长度 X

        Map<Integer, List<Integer>> mapDict = new HashMap<>();  // 存储每个长度对应的最优切割方式
        int[] dp = new int[X + 1];  // dp 数组，存储每个长度对应的最大收益

        // 初始化 dp 数组
        for (int i = 1; i <= X; i++) {
            dp[i] = i;
            mapDict.put(i, new ArrayList<>());
            mapDict.get(i).add(i);  // 每个长度的最小切割方式就是它自己

            // 对每个 i，尝试切割成两个部分 j 和 (i-j)
            for (int j = 1; j <= i / 2; j++) {
                int count = dp[j] * dp[i - j];  // 当前切割的收益
                List<Integer> newList = new ArrayList<>(mapDict.get(j));  // 当前切割方案
                newList.addAll(mapDict.get(i - j));  // 合并切割方案

                // 如果当前切割方案收益更大或切割方式更优，更新 dp 数组和切割方式
                if (count > dp[i] || (count == dp[i] && shouldUpdateList(mapDict.get(i), mapDict.get(j), mapDict.get(i - j)))) {
                    dp[i] = count;
                    mapDict.put(i, newList);
                }
            }
        }

        // 输出最优的切割方式
        List<Integer> resultList = mapDict.get(X);
        System.out.println(String.join(" ", resultList.stream().map(Object::toString).toArray(String[]::new)));

        scanner.close();
    }
}